package service

import (
	"bufio"
	"errors"
	"fmt"
	"net"
)

type service interface {
}

type serviceProperty struct {
	connSlice []*net.TCPConn
	listenTCP *net.TCPListener
}

func MakeService() serviceProperty {
	// 解析 tcp 服务
	tcpAddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:9999")
	if err != nil {
		fmt.Println("net.ResolverTcpAddr error: ", err)
		return serviceProperty{}
	}

	// 监听指定 tcp 服务
	listenTCP, err := net.ListenTCP("tcp", tcpAddr)
	if err != nil {
		fmt.Println("net.ListenTCP error:", err)
		return serviceProperty{}
	}

	return serviceProperty{
		connSlice: []*net.TCPConn{},
		listenTCP: listenTCP,
	}
}

func (s *serviceProperty) RunService() {
	defer s.listenTCP.Close()

	for {
		tcpConn, err := s.listenTCP.AcceptTCP()
		if err != nil {
			return
		}

		fmt.Println("A client connected:", tcpConn.RemoteAddr().String())

		//当有一个客户端进来之时，广播某某进入房间
		s.broadcastMessage(tcpConn.RemoteAddr().String() + "加入房间\n")

		s.connSlice = append(s.connSlice, tcpConn)

		// 监听到被访问，开启一个协程
		go s.tcpPipe(tcpConn)
	}
}

// 对客户端作出反应
func (s *serviceProperty) tcpPipe(conn *net.TCPConn) {
	ipStr := conn.RemoteAddr().String()

	fmt.Println(ipStr)

	defer func() {
		s.deleteConn(conn)
		conn.Close()
		s.broadcastMessage(ipStr + "离开房间\n")
	}()

	reader := bufio.NewReader(conn)

	for {
		massage, err := reader.ReadString('\n')

		if massage != "\n" {
			return
		}

		massage = fmt.Sprintf("%s说:%s", ipStr, massage)

		if err != nil {
			return
		}

		// 广播消息
		fmt.Println(massage)

		err = s.broadcastMessage(massage)
		if err != nil {
			fmt.Println(err)
			return
		}
	}
}

// 广播数据
func (s *serviceProperty) broadcastMessage(massage string) error {
	b := []byte(massage)

	for _, conn := range s.connSlice {
		fmt.Println(conn)

		_, err := conn.Write(b)
		if err != nil {
			fmt.Println("发送给", conn.RemoteAddr().String(), "数据失败"+err.Error())
			return err
		}
	}

	return nil
}

// 移除已经关闭的客户端
func (s *serviceProperty) deleteConn(conn *net.TCPConn) error {

	if conn == nil {
		fmt.Println("conn is nil")
		return errors.New("conn is nil")
	}

	for i := 0; i < len(s.connSlice); i++ {
		if conn == s.connSlice[i] {
			s.connSlice = append(s.connSlice[:i], s.connSlice[i+1:]...)
			break
		}
	}

	return nil
}
